﻿using NM.Module.SafeResponse.Middleware.Configurations;
using FrameworkCore.DI;
using Microsoft.Extensions.Options;
using System.Security.Cryptography;
using System.Text;

namespace NM.Module.SafeResponse.Middleware.EncryptHelpers;

/// <summary>
/// 非对称加密提供者
/// </summary>
public class RSAProvider : ITransientDependency
{
    private readonly IOptions<SecretSettings> _optSecretSettings;
    private readonly RSACryptoServiceProvider _rsaProvider;

    public RSAProvider(IOptions<SecretSettings> optSecretSettings)
    {
        _optSecretSettings = optSecretSettings;
        _rsaProvider = new RSACryptoServiceProvider(2048);
    }

    /// <summary>
    /// 生成密钥
    /// </summary>
    /// <param name="rsaProvider"></param>
    public void GenerateKeys(out RSACryptoServiceProvider rsaProvider)
    {
        rsaProvider = _rsaProvider;
    }

    /// <summary>
    /// 使用公钥加密明文数据。
    /// </summary>
    /// <param name="plainText">要加密的明文。</param>
    /// <param name="publicKey">公钥</param>
    /// <returns>加密后的数据（Base64字符串）。</returns>
    public string Encrypt(string plainText, string? publicKey = default)
    {
        _rsaProvider.FromXmlString(publicKey ?? _optSecretSettings.Value.RSASecret.PublicKey);
        byte[] bytesToEncrypt = Encoding.UTF8.GetBytes(plainText);
        byte[] bytesEncrypted = _rsaProvider.Encrypt(bytesToEncrypt, true);
        return Convert.ToBase64String(bytesEncrypted);
    }

    /// <summary>
    /// 使用私钥解密数据。
    /// </summary>
    /// <param name="cipherText">要解密的加密数据（Base64字符串）。</param>
    /// <param name="privateKey">私钥</param>
    /// <returns>解密后的明文。</returns>
    public string Decrypt(string cipherText, string? privateKey = default)
    {
        _rsaProvider.FromXmlString(privateKey ?? _optSecretSettings.Value.RSASecret.PrivateKey);
        byte[] bytesToDecrypt = Convert.FromBase64String(cipherText);
        byte[] bytesDecrypted = _rsaProvider.Decrypt(bytesToDecrypt, true);
        return Encoding.UTF8.GetString(bytesDecrypted);
    }


    /// <summary>
    /// 使用私钥创建数字签名
    /// </summary>
    /// <param name="data">要签名的原始数据字符串。</param>
    /// <param name="privateKey">包含私钥的RSACryptoServiceProvider实例。RSA加密服务提供程序，用于生成签名。</param>
    /// <returns>返回基于SHA256散列算法和PKCS#1填充的数字签名的Base64编码字符串。</returns>
    public string CreateSignature(string data, string? privateKey = default)
    {
        _rsaProvider.FromXmlString(privateKey ?? _optSecretSettings.Value.RSASecret.PrivateKey);
        byte[] dataToSign = Encoding.UTF8.GetBytes(data);
        return Convert.ToBase64String(_rsaProvider.SignData(dataToSign, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1));
    }

    /// <summary>
    /// 使用公钥校验数字签名
    /// </summary>
    /// <param name="data">要验证签名的原始数据字符串。</param>
    /// <param name="signature">要验证的签名，应为Base64编码字符串。</param>
    /// <param name="publicKey">公钥</param>
    /// <returns>如果签名验证成功，则返回true；否则返回false。</returns>
    public bool ValidateSignature(string data, string signature, string? publicKey = default)
    {
        _rsaProvider.FromXmlString(publicKey ?? _optSecretSettings.Value.RSASecret.PublicKey);
        byte[] dataToVerify = Encoding.UTF8.GetBytes(data);
        byte[] signatureBytes = Convert.FromBase64String(signature);
        return _rsaProvider.VerifyData(dataToVerify, signatureBytes, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1);
    }

    /// <summary>
    /// 获取公钥
    /// </summary>
    /// <returns></returns>
    public string GetPublicKey()
    {
        return _rsaProvider.ToXmlString(false);
    }

    /// <summary>
    /// 获取密钥
    /// </summary>
    /// <returns></returns>
    public string GetPrivateKey()
    {
        return _rsaProvider.ToXmlString(true);
    }
}

